/**
 * File Name: AquariumObject.java
 *
 * Date: 18/12/2009
 *
 * Copyright (c) 2006 Michael LaLena. All rights reserved.  (www.lalena.com)
 * Permission to use, copy, modify, and distribute this Program and its documentation,
 *  if any, for any purpose and without fee is hereby granted, provided that:
 *   (i) you not charge any fee for the Program, and the Program not be incorporated
 *       by you in any software or code for which compensation is expected or received;
 *   (ii) the copyright notice listed above appears in all copies;
 *   (iii) both the copyright notice and this Agreement appear in all supporting documentation; and
 *   (iv) the name of Michael LaLena or lalena.com not be used in advertising or publicity
 *          pertaining to distribution of the Program without specific, written prior permission.
 */
package model;

import gui.Constanten;
import java.awt.*;

/**
 * Basisklasse waarvan alle andere objecten die in een aquarium zullen zitten zal worden afgeleidt.
 *
 * @author Michiel Declercq
 * @author Stijn Delbeke
 * @author Dieter Deriemaeker
 * @author Gregory Nickmans
 *
 * @author Michael LaLena
 *
 */
public abstract class AquariumObject {

    /**
     * De afstand vanaf waar objecten zich van elkaar moeten verwijderen
     */
    public static int SeparationRange = Constanten.SEPARATE_DISTANCE;

    /**
     * De horizon waarbinnen ze andere objecten kunnen waarnemen
     */
    public static int DetectionRange = Constanten.DETECTION_DISTANCE;

    /**
     * De coördinaten van het object
     */
    protected Point location;

    /**
     * De grootte van het object
     */
    protected Dimension size;

    /**
     * De kleur van het object
     */
    private Color color;

    /**
     * De grootte van het veld
     */
    protected static Dimension map = new Dimension(Constanten.CANVAS_WIDTH, Constanten.CANVAS_HEIGHT);

    /**
     * Constructor
     * @param x x-coördinaat
     * @param y y-coördinaat
     * @param dim Grootte van het object
     * @param color Kleur van het object
     */
    public AquariumObject(int x, int y, Dimension dim, Color color) {
        this.location = new Point(x, y);
        this.size = dim;
        this.color = color;
    }

    /**
     * Geeft de kleur van het object
     * @return Color
     */
    public Color getColor() {
        return color;
    }

    /**
     * Geeft de locatie terug
     * @return Point
     */
    public Point getLocation() {
        return location;
    }

    /**
     *
     * @return Grootte van het object
     */
    public Dimension getSize() {
        return size;
    }

    /**
     * Stelt de kleur in van het object
     * @param kleur
     */
    public void setColor(Color kleur) {
        color = kleur;
    }

    /**
     * Geeft de afstand tussen het object en een punt terug
     *
     * @param p Het punt waarvan men de afstand tot het object wil weten
     * @return int
     */
    public int getDistance(Point p) {
        int dX = p.x - location.x;
        int dY = p.y - location.y;

        return (int) Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2));
    }

    /**
     * Voegt 2 punten samen, afhankelijk van hun gewicht dat is toegekend
     *
     * @param  p1 Het eerste punt
     * @param  w1 Het gewicht van het eerste punt
     * @param  p2 Het tweede punt
     * @param  w2 Het gewicht van het tweede punt
     * @return Point
     */
    protected Point sumPoints(Point p1, double w1, Point p2, double w2) {
        return new Point((int) (w1 * p1.x + w2 * p2.x), (int) (w1 * p1.y + w2 * p2.y));
    }

    /**
     * De afstand van de linkerbovenhoek van de map tot een opgegeven punt
     *
     * @param  p Het punt waarvan men de afstand wil weten
     * @return double
     */
    private double sizeOfPoint(Point p) {
        return Math.sqrt(Math.pow(p.x, 2) + Math.pow(p.y, 2));
    }

    /**
     * Normaliseert een punt.
     *
     * @param  p Het punt dat genormaliseerd moet worden
     * @param  n De normalisatiewaarde
     * @return Point
     */
    protected Point normalisePoint(Point p, double n) {
        if (sizeOfPoint(p) == 0.0) {
            return p;
        }
        else {
            double weight = n / sizeOfPoint(p);
            return new Point((int) (p.x * weight), (int) (p.y * weight));
        }
    }

    /**
     * Zoekt het dichtst bijzijnde punt, ook al is deze van de map
     *
     * @param  p Het punt waar we het dichtst bijzijnde punt moeten hebben
     * @param  anderPunt Het punt om de afstand van te meten
     * @return Point
     */
    public Point closestLocation(Point p, Point anderPunt) {
        int dX = Math.abs(anderPunt.x - p.x);
        int dY = Math.abs(anderPunt.y - p.y);
        int x = anderPunt.x;
        int y = anderPunt.y;

        // controle of een punt dat aan de andere kant is van de map,
        // dichterbij het meegegeven punt ligt
        if (Math.abs(map.width - anderPunt.x + p.x) < dX) {
            dX = map.width - anderPunt.x + p.x;
            x = anderPunt.x - map.width;
        }
        if (Math.abs(map.width - p.x + anderPunt.x) < dX) {
            dX = map.width - p.x + anderPunt.x;
            x = anderPunt.x + map.width;
        }

        if (Math.abs(map.height - anderPunt.y + p.y) < dY) {
            dY = map.height - anderPunt.y + p.y;
            y = anderPunt.y - map.height;
        }
        if (Math.abs(map.height - p.y + anderPunt.y) < dY) {
            dY = map.height - p.y + anderPunt.y;
            y = anderPunt.y + map.height;
        }

        return new Point(x, y);
    }

    /**
     * Beweegt de objecten
     * @param nieuweRichting De richting waarin het object moet bewegen
     */
    public void move(int nieuweRichting) {
    }
}
